from model import Stimuli, Subject, Tester
from model.stage import SingleStage, MultiStage, DecisionStage, StageHandler, \
    EmptyStage, PresentationStage, AppearanceStage
from multineuro import game
from multineuro.sprite import ImgSprite, ButtonSprite
from sprite import MonkeySprite
import properties
from properties import trial_config

"""Experiment with a subject, a tester and flowers."""
class CasualLearning(game.Game):

    def __init__(self, name):
        """Receives the name of the experiment."""
        super(CasualLearning, self).__init__(name, properties.FULLSCREEN)
        self.resources = {}
        self.stage_options = {'S': SingleStage,
                              'M': MultiStage,
                              'D': DecisionStage}
        self._load_sprites()
        self._load_sounds()
        self._load_objects()
        self._load_stages()
        self.stage_handler.begin(self.next_button)

    def _load_stages(self):
        self._build_stages(properties.trial_config)
        self.stage_handler = StageHandler(self.stages)
        self.stage_handler.suscribe('finnish' , lambda x: self.game_over())


    def _build_stages(self, trial_configs):
        empty = EmptyStage([self.subject, self.tester, self.stimuli])
        show_test = PresentationStage(self.tester)
        show_subject = PresentationStage(self.subject)
        stimuli_presentation = [PresentationStage(stimulus)
                                for stimulus in self.stimuli.available.values()]
        instance = AppearanceStage(self.subject,
                                   self.tester,
                                   self.stimuli.available)
        trials = self._initialize_trials(trial_configs)
        self.stages = [empty, show_test, show_subject] + stimuli_presentation + [instance] + trials

    def _initialize_trials(self, trial_configs):
        trials = []
        for trial_config in trial_configs:
            clazz = self.stage_options[trial_config.class_code]
            trial = clazz(trial_config.names, self.stimuli.available)
            trials.append(trial)
        return trials

    def _load_objects(self):
        ''' Hole. '''
        self.stimuli = Stimuli(self.resources['stimuli'], properties.trial_config)
        self.subject = Subject(self.resources['subject_sprite'], self.resources['cry'])
        self.tester = Tester(self.resources['tester_sprite'], self.subject, self.stimuli)
        self.subject.sprite.suscribe('position', lambda x: self.tester.test(self.subject))

    def _load_sounds(self):
        self.resources['cry'] = self._load_sound(properties.subject.action_snd)

    def _load_sprites(self):
        #TODO Use normalized position ([0..1])

        #Adds hidden buttons
        self.next_button = ButtonSprite('top-right')
        self.resources['button'] = self.next_button
        self.add_active_sprite(self.resources['button'])

        #Adds subject (foreground)
        self.resources['subject_sprite'] = MonkeySprite(ImgSprite(properties.subject.normal, properties.subject.pos),
                                                          [ImgSprite(properties.subject.action, (0, 0))])
        self.add_active_sprite(self.resources['subject_sprite'])

        #Adds tester (background)
        self.resources['tester_sprite'] = ImgSprite(properties.tester.image, properties.tester.pos)
        self.add_background_sprite(self.resources['tester_sprite'])

        #Adds estimulus (static not-background)
        self.resources['stimuli'] = {}
        for estimuli in properties.estimulus:
            estim = ImgSprite(estimuli.image)
            self.resources['stimuli'][estimuli.name] = estim
            self.add_background_sprite(estim)




